import {ResultType, PostMethod, RequestParameter} from "@/typing/request";
import * as qs from "qs";
import axios from "axios";
import {ResultUtils} from "@/utils/ResultUtils";

const TIME_OUT = 5 * 1000;

let urlPrefix = "";

export namespace RequestUtils {

    export function setUrlPrefix(prefix: string) {
        urlPrefix = prefix;
    }

    function request<T>(parameter: RequestParameter) {

        let {url, headers, timeout, method, data, retry, release} = parameter;

        let _timeout = typeof timeout === "undefined" ? TIME_OUT : timeout;
        let _headers = typeof headers === "undefined" ? {} : headers;
        let _method = typeof method === "undefined" ? PostMethod.POST : method;
        let _retryCount = typeof retry === "undefined" ? 0 : retry;
        let _release = typeof release === "undefined" ? true : release;

        let contentTypeFormData = "multipart/form-data; charset=UTF-8";
        let contentTypeFormUrlencoded = "application/x-www-form-urlencoded; charset=UTF-8";
        let contentTypeJson = "application/json; charset=UTF-8";
        let contentType = "Content-Type"

        const configData: any = {
            url: `${urlPrefix}${url}`,
            timeout: _timeout,
            headers: _headers,
            retry: _retryCount,
            release: _release,
        };

        switch (_method) {
            case PostMethod.GET:
                configData.params = data;
                break;
            case PostMethod.POST_FORM:
                configData.method = PostMethod.POST;
                if (data instanceof FormData) {
                    configData.headers[contentType] = contentTypeFormData;
                    configData.data = data;
                } else {
                    configData.headers[contentType] = contentTypeFormUrlencoded;
                    configData.data = qs.stringify(data);
                }
                break;
            default:
                configData.method = PostMethod.POST;
                configData.headers[contentType] = contentTypeJson;
                configData.data = data;
        }

        return new Promise<ResultType<T | null>>((resolve, reject) => {
            axios(configData)
                .then((result) => {
                    resolve(result.data);
                })
                .catch((error) => {
                    const {status, message} = error;
                    try {
                        if (message.includes("timeout")) {
                            resolve(ResultUtils.error(null));
                        } else {
                            resolve(ResultUtils.error(error));
                        }
                    } catch (e) {
                        resolve(ResultUtils.error(error));
                    }
                });
        });
    }


    export function post<T>(data: RequestParameter) {
        data.method = PostMethod.POST;
        return request<T>(data);
    }

    export function get<T>(data: RequestParameter) {
        data.method = PostMethod.GET;
        return request<T>(data);
    }
}